Next: Errors, Previous: Catch and Throw, Up: Nonlocal Exits [Contents][Index]
catch and
throwOne way to use catch and throw is to
exit from a doubly nested loop. (In most languages, this would be
done with a goto.) Here we compute (foo
i j) for i and
j varying from 0 to 9:
(defun search-foo ()
(catch 'loop
(let ((i 0))
(while (< i 10)
(let ((j 0))
(while (< j 10)
(if (foo i j)
(throw 'loop (list i j)))
(setq j (1+ j))))
(setq i (1+ i))))))
If foo ever returns non-nil, we stop
immediately and return a list of i and j.
If foo always returns nil, the
catch returns normally, and the value is
nil, since that is the result of the
while.
Here are two tricky examples, slightly different, showing two
return points at once. First, two return points with the same
tag, hack:
(defun catch2 (tag)
(catch tag
(throw 'hack 'yes)))
⇒ catch2
(catch 'hack (print (catch2 'hack)) 'no) ⊣ yes ⇒ no
Since both return points have tags that match the
throw, it goes to the inner one, the one established
in catch2. Therefore, catch2 returns
normally with value yes, and this value is printed.
Finally the second body form in the outer catch,
which is 'no, is evaluated and returned from the
outer catch.
Now let’s change the argument given to
catch2:
(catch 'hack (print (catch2 'quux)) 'no) ⇒ yes
We still have two return points, but this time only the outer
one has the tag hack; the inner one has the tag
quux instead. Therefore, throw makes
the outer catch return the value yes.
The function print is never called, and the
body-form 'no is never evaluated.
Next: Errors, Previous: Catch and Throw, Up: Nonlocal Exits [Contents][Index]